package com.yuma.tingshu.order.listener;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.rabbitmq.client.Channel;
import com.yuma.tingshu.common.constant.RabbitConstant;
import com.yuma.tingshu.common.constant.RedisConstant;
import com.yuma.tingshu.common.constant.SystemConstant;
import com.yuma.tingshu.model.order.OrderDetail;
import com.yuma.tingshu.model.order.OrderInfo;
import com.yuma.tingshu.order.mapper.OrderDetailMapper;
import com.yuma.tingshu.order.mapper.OrderInfoMapper;
import com.yuma.tingshu.vo.user.UserPaidRecordVo;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.amqp.core.ExchangeTypes;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.io.IOException;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Component
public class OrderListener {

    @Autowired
    private OrderInfoMapper orderInfoMapper;
    @Autowired
    private OrderDetailMapper orderDetailMapper;
    @Autowired
    private RabbitTemplate rabbitTemplate;
    @Autowired
    private RedisTemplate redisTemplate;

    //关单
    @RabbitListener(queues = RabbitConstant.ORDER_DEAD_QUEUE)
    public void closeOrder(String orderNo, Channel channel, Message message) throws IOException {
        // 1.判空
        if (StringUtils.isBlank(orderNo)) {
            channel.basicReject(message.getMessageProperties().getDeliveryTag(), false);
            return;
        }
        // 2.幂等
        String idemKey = RedisConstant.ORDER_DEAD_IDEM_PREFIX + orderNo;
        try {
            if (!redisTemplate.opsForValue().setIfAbsent(idemKey, "1", RedisConstant.ALBUM_TIMEOUT, TimeUnit.SECONDS)) {
                channel.basicReject(message.getMessageProperties().getDeliveryTag(), false);
                return;
            }
            // 3.更新订单状态为取消状态
            if (1 == orderInfoMapper.updateStatus(orderNo, SystemConstant.ORDER_STATUS_UNPAID, SystemConstant.ORDER_STATUS_CANCEL)) {
                channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
            } else {
                channel.basicReject(message.getMessageProperties().getDeliveryTag(), false);
            }
        } catch (Exception e) {
            // 数据库操作异常
            if (!message.getMessageProperties().getRedelivered()) {
                redisTemplate.delete(idemKey);
                channel.basicReject(message.getMessageProperties().getDeliveryTag(), true);
            } else {
                channel.basicReject(message.getMessageProperties().getDeliveryTag(), false);
            }
        }
        channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
    }

    @Transactional
    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(RabbitConstant.ORDER_PAID_QUEUE),
            exchange = @Exchange(value = RabbitConstant.ORDER_EXCHANGE, type = ExchangeTypes.TOPIC, ignoreDeclarationExceptions = "true"),
            key = RabbitConstant.ORDER_PAID_RK
    ))
    public void paidOrder(String orderNo, Channel channel, Message message) throws IOException {
        // 1.判空
        if (StringUtils.isBlank(orderNo)) {
            channel.basicReject(message.getMessageProperties().getDeliveryTag(), false);
            return;
        }
        // 2.幂等性setIfAbsent
        String idemKey = RedisConstant.ORDER_PAID_IDEM_PREFIX + orderNo;
        if (!redisTemplate.opsForValue().setIfAbsent(idemKey, orderNo, RedisConstant.ALBUM_TIMEOUT, TimeUnit.SECONDS)) {
            channel.basicReject(message.getMessageProperties().getDeliveryTag(), false);
            return;
        }
        try {
            // 3.根据订单编号查询订单（order_info主键不是order_no）
            OrderInfo orderInfo = this.orderInfoMapper.selectOne(new LambdaQueryWrapper<OrderInfo>()
                    .eq(OrderInfo::getOrderNo, orderNo));
            // 对象判空
            if (ObjectUtils.isEmpty(orderInfo)) {
                channel.basicReject(message.getMessageProperties().getDeliveryTag(), false);
                return;
            }
            // 4.更新订单状态为已支付状态, 从0901更新到0902，初始状态必须是0901才更新
            // 把某个状态更新到另一个状态
            int updateCountRow = orderInfoMapper.updateStatus(orderNo, SystemConstant.ORDER_STATUS_UNPAID, SystemConstant.ORDER_STATUS_PAID);
            if (updateCountRow == 1) {
                // 更新成功,发送消息给MQ，记录购买行为
                // 4.1组装消息的内容
                UserPaidRecordVo userPaidRecordVo = new UserPaidRecordVo();
                userPaidRecordVo.setOrderNo(orderNo);
                userPaidRecordVo.setUserId(orderInfo.getUserId());
                userPaidRecordVo.setItemType(orderInfo.getItemType());
                // 根据订单编号查询订单明细
                List<OrderDetail> orderDetails = orderDetailMapper.selectList(new LambdaQueryWrapper<OrderDetail>()
                        .eq(OrderDetail::getOrderId, orderInfo.getId()));
                // 判空
                if (!CollectionUtils.isEmpty(orderDetails)) {
                    // 拿出详情对象中每个item_id，VIP是vip表id,Album是album表id
                    List<Long> itemIdList = orderDetails.stream().map(OrderDetail::getItemId).toList();
                    userPaidRecordVo.setItemIdList(itemIdList);
                }
                // 发送给RabbitMg -> UserListener
                rabbitTemplate.convertAndSend(RabbitConstant.ORDER_EXCHANGE, RabbitConstant.USER_PAID_RK, JSON.toJSONString(userPaidRecordVo));
                // 应答
                channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
            } else {
                // TODO：4.2 修改失败 之前的操作都要撤销(钱给退回去) user_account钱 根据user_account_detail查询此orderNo加回去
                // 应答
                channel.basicReject(message.getMessageProperties().getDeliveryTag(), false);
            }
        } catch (Exception e) {
            // 数据库操作异常
            if (!message.getMessageProperties().getRedelivered()) {
                redisTemplate.delete(idemKey);
                channel.basicReject(message.getMessageProperties().getDeliveryTag(), true);
            } else {
                channel.basicReject(message.getMessageProperties().getDeliveryTag(), false);
            }
        }
        channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
    }
}